﻿#include "socketlibfunction.h"

#if defined PLATFORM_WINDOWS
WSADATA SocketLib::SocketApi::g_WSAData;
#endif

void SocketLib::SocketApi::InitSocket()
{
    #if defined PLATFORM_WINDOWS
    static bool WinSockIsInit = false;
    if(!WinSockIsInit)
    {
        WSAStartup(MAKEWORD(2,2), &g_WSAData);
        WinSockIsInit = true;
    }
    #endif
}

void SocketLib::SocketApi::DestorySocket()
{
    #if defined PLATFORM_WINDOWS
    WSACleanup();
    #endif
}

bool SocketLib::SocketApi::SetNonblock(sock aSocket, bool bBlock)
{
    int err;
    unsigned long ul = bBlock;
    #if defined PLATFORM_WINDOWS
    err = ioctlsocket(aSocket, FIONBIO, &ul);
    #else
    err = ioctl( aSocket, FIONBIO, &ul);
    #endif
    return err != SOCKET_ERROR;
}

sock SocketLib::SocketApi::MakeConnect(const char* pServerip, int aServerPort)
{
    InitSocket();

    struct sockaddr_in server_addr;

    sock clientfd = socket(AF_INET, SOCK_STREAM, 0);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(aServerPort);
    server_addr.sin_addr.s_addr = inet_addr(pServerip);

    sock s = SOCKET_ERROR;

    while((s = connect(clientfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr))) < 0)
    {
        if(EINTR == sErrno)
        {
            continue;
        }
    }

    return clientfd;
}

sock SocketLib::SocketApi::MakeListen(int aPort, int aBacknum)
{
    InitSocket();

    sock socketfd;
    struct  sockaddr_in server_addr;
    socketfd = socket(AF_INET, SOCK_STREAM, 0);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(aPort);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    if(bind(socketfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
    {
        CloseSocket(socketfd);
        return SOCKET_ERROR;
    }

    if(listen(socketfd, aBacknum) == SOCKET_ERROR)
    {
        CloseSocket(socketfd);
        return SOCKET_ERROR;
    }

    return socketfd;
}

void SocketLib::SocketApi::CloseSocket(sock aSock)
{
    #if defined PLATFORM_WINDOWS
    closesocket(aSock);
    #else
    close(aSock);
    #endif
}

const char* SocketLib::SocketApi::GetIP(unsigned int aIP)
{
    struct in_addr addr;
    addr.s_addr = htonl(aIP);
    return inet_ntoa(addr);
}

int SocketLib::SocketApi::SendData(sock aSock, const char* pBuffer, int aBufferLen)
{
    int transnum = send(aSock, pBuffer, aBufferLen, 0);
    if(transnum < 0)
    {
        if(S_EWOULDBLOCK == sErrno)
        {
            transnum = 0;
        }
    }

    // send error, if transnum < 0
    return transnum;
}
